package cn.ztydata.teachingsystem.heaven.dao.redis;

import cn.ztydata.teachingsystem.heaven.entity.KnowledgePoint;
import cn.ztydata.teachingsystem.heaven.entity.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.stereotype.Repository;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 资源知识点Redis类
 *
 * @author fanruiping
 * @since 2014-12-08
 */
@Repository
public class ResourceKpDao extends BaseRedisDao {
    @Autowired
    private KpResourceDao kpResourceDao;
    /**
     * 获取资源包含的知识点编号集合
     * @param resourceId
     * @return Set
     *
     * @author fanruiping
     * @since 2014-12-11
     */
    public Set<Long> getKpIds(long resourceId){
        //获取Set操作
        SetOperations<String, Long> setOperations = redisTemplate.opsForSet();

        logger.debug("return resource kpIds");

        return setOperations.members(KeyUtils.resourceKp(resourceId));
    }

    /**
     * 获取资源包含的知识点编号集合
     * @param rscIds
     * @return List
     *
     * @author fanruiping
     * @since 2014-12-11
     */
    public Set<Long> getKpIdsByRscIds(List<Long> rscIds){
        //获取Set操作
        SetOperations<String, Long> setOperations = redisTemplate.opsForSet();



        Set<Long> rscKpIds = new HashSet<>();

        logger.debug("循环获取资源编号:Long resourceId : rscIds");
        for(Long resourceId : rscIds){
            rscKpIds.addAll(setOperations.members(KeyUtils.resourceKp(resourceId)));
        }

        logger.debug("return resource kpIds By resourceIds");

        return rscKpIds;
    }

    /**
     * 保存资源与知识点的关系
     * @param resource 资源实体
     * @return Boolean
     *
     * @author fanruiping
     * @since 214-12-11
     */
    public Boolean addKp(final Resource resource) {
        SessionCallback<Boolean> sessionCallback = new SessionCallback<Boolean>() {
            @Override
            public Boolean execute(RedisOperations operations) throws DataAccessException {
                operations.multi();
                //获取Set操作
                SetOperations<String, Long> setOperations = operations.opsForSet();

                logger.debug("循环资源关键字列表:KnowledgePoint kp : resource.getKps()");
                for (KnowledgePoint kp : resource.getKps()){
                    //保存资源与知识点的关系
                    setOperations.add(KeyUtils.resourceKp(resource.getId()), kp.getId());

                    //保存知识点与资源的关系
                    setOperations.add(KeyUtils.kpResource(kp.getId()), resource.getId());

                    //递增知识点被使用次数
                    kpResourceDao.incrUsedTimes(kp.getId());
                }


                operations.exec();
                return true;
            }
        };

        logger.debug("return 新增资源关键字关系执行结果");

        return (Boolean)redisTemplate.execute(sessionCallback);
    }

    /**
     * 删除资源与知识点的关系(一个)
     * @param kpId 知识点编号
     * @param resourceId 资源编号
     * @return Boolean
     *
     * @author fanruiping
     * @since 2014-12-11
     */
    public Boolean deleteKp(final long resourceId, final long kpId) {
        SessionCallback<Boolean> sessionCallback = new SessionCallback<Boolean>() {
            @Override
            public Boolean execute(RedisOperations operations) throws DataAccessException {
                operations.multi();
                //获取Set操作
                SetOperations<String, Long> setOperations = operations.opsForSet();

                //删除资源与知识点的关系
                setOperations.remove(KeyUtils.resourceKp(resourceId), kpId);

                //删除知识点与资源的关系
                setOperations.remove(KeyUtils.kpResource(kpId), resourceId);

                operations.exec();
                return true;
            }
        };

        logger.debug("execute delete resource kp");

        return (Boolean)redisTemplate.execute(sessionCallback);
    }

    /**
     * 删除资源的所有知识点
     * @param id
     * @return Boolean
     *
     * @author fanruiping
     * @since 2014-12-13
     */
    public Boolean deleteKps(final Long id) {
        //获取资源的所有知识点编号集合
        final Set<Long> kpIds = this.getKpIds(id);

        if(kpIds.isEmpty()){
            logger.debug("kpId set is empty:kpIds.isEmpty()");

            return true;
        }

        SessionCallback<Boolean> sessionCallback = new SessionCallback<Boolean>() {
            @Override
            public Boolean execute(RedisOperations operations) throws DataAccessException {
                operations.multi();
                //获取Set操作
                SetOperations<String, Long> setOperations = operations.opsForSet();

                logger.debug("循环知识点编号集合:Long kpId : kpIds");
                for(Long kpId : kpIds){
                    //删除资源与知识点的关系
                    setOperations.remove(KeyUtils.resourceKp(id), kpId);

                    //删除知识点与资源的关系
                    setOperations.remove(KeyUtils.kpResource(kpId), id);
                }

                operations.exec();
                return true;
            }
        };

        logger.debug("返回删除资源知识点执行结果");

        return (Boolean)redisTemplate.execute(sessionCallback);
    }
}
